package com.tourism.service.impl;


import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tourism.core.common.exception.CustomException;
import com.tourism.core.common.utils.ResultCodeEnum;
import com.tourism.core.common.utils.WebUtils;
import com.tourism.core.security.entity.LoginUser;
import com.tourism.core.security.util.SecurityHolderUtils;
import com.tourism.domain.dto.user.AssignRoleDTO;
import com.tourism.domain.dto.user.UserPasswordDTO;
import com.tourism.domain.dto.user.UserProfileDTO;
import com.tourism.domain.dto.user.UserQueryDTO;
import com.tourism.domain.entity.Role;
import com.tourism.domain.entity.User;
import com.tourism.domain.entity.UserRole;
import com.tourism.mapper.RoleMapper;
import com.tourism.mapper.UserMapper;
import com.tourism.mapper.UserRoleMapper;
import com.tourism.service.MenuService;
import com.tourism.service.UserService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;


/**
 * 用户服务实现类
 *
 * @author lucky
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {

    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private MenuService menuService;


    @Override
    public boolean save(User entity) {
        String pwd = passwordEncoder.encode(entity.getPassword() );
        entity.setPassword(pwd);

        return super.save(entity);
    }

    @Override
    public boolean updateById(User entity) {
        return super.updateById(entity);
    }

    @Override
    public User getById(Long id) {
        User user = baseMapper.selectById(id);
        List<Role> roles = roleMapper.getRolesByUserId(user.getId());
        user.setRoles(new HashSet<>(roles));
        return user;
    }

    @Override
    public Page<User> getPage(Integer pIndex, Integer pSize, UserQueryDTO userQueryDTO) {
        String username = userQueryDTO.getUsername();
        Integer gender = userQueryDTO.getGender();
        Integer status = userQueryDTO.getStatus();
        String mobile = userQueryDTO.getMobile();
        String email = userQueryDTO.getEmail();

        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        lqw.like(StrUtil.isNotBlank(username), User::getUsername, username);
        lqw.eq(gender != null, User::getGender, gender);
        lqw.eq(status != null, User::getStatus, status);
        lqw.like(StrUtil.isNotBlank(mobile), User::getMobile, mobile);
        lqw.like(StrUtil.isNotBlank(email), User::getEmail, email);

        Page<User> page = new Page<>(pIndex, pSize);

        return page(page, lqw);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean assignRole(AssignRoleDTO assignRoleDTO) {
        // 删除用户角色
        userRoleMapper.delete(new LambdaQueryWrapper<UserRole>().eq(UserRole::getUserId, assignRoleDTO.getUserId()));

        // 判断用户分配的角色是否为空
        if (ObjectUtil.isNotEmpty(assignRoleDTO.getRoleIds())) {
            userRoleMapper.insertBatch(assignRoleDTO);
        }

        // 如果当前用户是分配角色的用户，则重新获取角色和权限
        LoginUser loginUser = SecurityHolderUtils.getLoginUser();
        Long userId = loginUser.getUser().getId();
        if(userId.equals(assignRoleDTO.getUserId())){
            List<Role> roles = roleMapper.getRolesByUserId(userId);
            loginUser.getUser().setRoles(new HashSet<>(roles));

            Set<String> permissions = menuService.getAuth();
            loginUser.getUser().setPermissions(permissions);

            List<SimpleGrantedAuthority> authorities = new ArrayList<>();
            permissions.forEach(perm -> {
                if (perm != null && !perm.trim().isEmpty()) {
                    authorities.add(new SimpleGrantedAuthority(perm));
                }
            });
            loginUser.setAuthorities(authorities);

            HttpServletRequest request = WebUtils.getRequest();
            String token = request.getHeader("Authorization");
            request.getSession().setAttribute("login_user:" + token, loginUser);
        }

        return true;
    }

    @Override
    public Boolean updateProfile(UserProfileDTO userProfileDTO) {
        HttpServletRequest request = WebUtils.getRequest();
        String token = request.getHeader("Authorization");

        HttpSession session = request.getSession();
        LoginUser loginUser = (LoginUser) session.getAttribute("login_user:" + token);

        User user = loginUser.getUser();
        user.setAvatar(userProfileDTO.getAvatar());
        user.setRealName(userProfileDTO.getRealName());
        user.setGender(userProfileDTO.getGender());
        user.setMobile(userProfileDTO.getMobile());
        user.setRemark(userProfileDTO.getRemark());

        loginUser.setUser(user);
        session.setAttribute("login_user:" + token, loginUser);

        return updateById(user);
    }

    @Override
    public Boolean updatePassword(UserPasswordDTO userPasswordDTO) {
        HttpServletRequest request = WebUtils.getRequest();
        String token = request.getHeader("Authorization");

        // 获取登录用户信息
        HttpSession session = request.getSession();
        LoginUser loginUser = (LoginUser) session.getAttribute("login_user:" + token);
        User user = loginUser.getUser();

        // 验证旧密码
        if(!passwordEncoder.matches(userPasswordDTO.getOldPwd(), user.getPassword())){
            throw new CustomException(ResultCodeEnum.OLD_PASSWORD_ERROR);
        }

        // 修改密码
        user.setPassword(passwordEncoder.encode(userPasswordDTO.getNewPwd()));

        return updateById(user);
    }

}




